﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Resources;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Devices;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Info;
using Boxi.ViewModel;
using Boxi.Model;
using Microsoft.Phone.Shell;
using Boxi.Extensions;
using Microsoft.Xna.Framework.Audio;


namespace Boxi
{

    public partial class MainPage : PhoneApplicationPage
    {
#region Fields
        private DateTime ThinkingStarted = default(DateTime);
        private const String GameKey = "Game";
        private TransformGroup transformGroup;
        private TranslateTransform translation;
        private ScaleTransform scale;
#endregion
#region Properties
        protected SolidColorBrush BackgroundColor
        {
            get
            {
                return Application.Current.Resources["PhoneBackgroundBrush"] as SolidColorBrush;
            }
        }
        protected SolidColorBrush ForegroundColor
        {
            get
            {
                Color color;
                if (Game.Theme == GameModel.ThemeType.Traditional)
                    color = Colors.Brown;
                else if (IsBackgroundDark)
                    color = Colors.White;
                else
                    color = Colors.Black;

                return new SolidColorBrush(color);
            }
        }
        protected Boolean IsBackgroundDark
        {
            get
            {
                return (BackgroundColor.Color != new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)).Color);
            }
        }
        private Boolean IsOverlayOpen
        {
            get
            {
                return rclOverlay.Visibility == Visibility.Visible ||
                       imgParchmentOverlay.Visibility == Visibility.Visible;
            }
            set
            {
                if (value)
                {
                    if (Game.Theme == GameModel.ThemeType.Traditional)
                    {
                        imgParchmentOverlay.Visibility = Visibility.Visible;
                        rclOverlay.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        imgParchmentOverlay.Visibility = Visibility.Collapsed;
                        rclOverlay.Visibility = Visibility.Visible;
                    }
                }
                else
                {
                    imgParchmentOverlay.Visibility = Visibility.Collapsed;
                    rclOverlay.Visibility = Visibility.Collapsed;
                }
            }
        }
        protected Boolean IsGameInProgress
        {
            get;
            set;
        }
        protected Boolean IsLoading
        {
            get;
            set;
        }
        protected GameView Game
        {
            get; 
            set;
        }
#endregion
#region Constructor
        /// <summary>
        /// Page Load
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            rclOverlay.Fill = BackgroundColor;

            transformGroup = new TransformGroup();
            translation = new TranslateTransform();
            scale = new ScaleTransform();

            transformGroup.Children.Add(scale);
            transformGroup.Children.Add(translation);
            cvsMain.RenderTransform = transformGroup;

            txtName1.Text = "Me";
            txtName2.Text = DeviceExtendedProperties.GetValue("DeviceName").ToString();

            //Player UI
            txtPlayer1Name.Text = txtName1.Text;
            txtPlayer2Name.Text = txtName2.Text;

            //ManipulationDelta += PhoneApplicationPage_ManipulationDelta;
            //ManipulationStarted += PhoneApplicationPage_ManipulationStarted;
            //ManipulationCompleted += PhoneApplicationPage_ManipulationCompleted;

        }
       
#endregion
#region Game Events
        protected void MoveActivationComplete(object sender, EventArgs e)
        {

        }
        protected void MoveMade(object PlayerChanged, Boxi.EventArguments.MoveMadeEventArgs e)
        {
            if (IsLoading)
                return;

            UpdateScore();
            var flashs = 7;
            var flashTimer = new DispatcherTimer();

            if (Game.Theme == GameModel.ThemeType.Arcade)
                ///////////////////////////////////////////////////////////////////////////
                // http://www.freesound.org/samplesViewSingle.php?id=88498               //
                // 22744__FranciscoPadilla__41_Low_Floor_Tom.wav Sound effect by HardPCM //
                ///////////////////////////////////////////////////////////////////////////
                PlaySound("22744__FranciscoPadilla__41_Low_Floor_Tom.wav");
            else
                /////////////////////////////////////////////////////////////
                // http://www.freesound.org/samplesViewSingle.php?id=68885 //
                //    68885__aboe__scribSHT4.wav Sound effect by Aboe      //
                /////////////////////////////////////////////////////////////
                PlaySound("68885__aboe__scribSHT4.wav");


            if (e.PointsScored.Length == 0)
            {
                Vibrate(30);
            }
            else if (e.PointsScored.Length == 1)
            {
                if (Game.Theme == GameModel.ThemeType.Arcade)
                    /////////////////////////////////////////////////////////////
                    // http://www.freesound.org/samplesViewSingle.php?id=32945 //
                    //   32945__HardPCM__Chip018.wav Sound effect by HardPCM   //
                    /////////////////////////////////////////////////////////////
                    PlaySound("32945__HardPCM__Chip018.wav");
                else
                    /////////////////////////////////////////////////////////////
                    // http://www.freesound.org/samplesViewSingle.php?id=68875 //
                    //     68875__aboe__scribLNG2.wav Sound effect by Aboe     //
                    /////////////////////////////////////////////////////////////
                    PlaySound("68875__aboe__scribLNG2.wav");

                Vibrate(100);
            }
            else
            {
                if (Game.Theme == GameModel.ThemeType.Arcade)
                    /////////////////////////////////////////////////////////////
                    // http://www.freesound.org/samplesViewSingle.php?id=32953 //
                    //   32953__HardPCM__Chip053.wav Sound effect by HardPCM   //
                    /////////////////////////////////////////////////////////////
                    PlaySound("32953__HardPCM__Chip053.wav");
                else
                    /////////////////////////////////////////////////////////////
                    // http://www.freesound.org/samplesViewSingle.php?id=68875 //
                    //     68875__aboe__scribLNG2.wav Sound effect by Aboe     //
                    /////////////////////////////////////////////////////////////
                    PlaySound("68875__aboe__scribLNG2.wav");
                Vibrate(200);
            }

            flashTimer.Interval = new TimeSpan(0, 0, 0, 0, 100);
            flashTimer.Tick += (obj, arg) => {
                if (flashs > 0)
                {
                    flashs -= 1;
                    e.Move.ElementUI.Opacity = (e.Move.ElementUI.Opacity == 1d) ? 0.2 : 1d;
                }
                else
                {
                    e.Move.ElementUI.Opacity = 0.62d;
                    ((DispatcherTimer)obj).Stop();
                }
            };
            flashTimer.Start();
            var gameRaw = Game.ToString();

            //Save for user leaves and comes back
            PhoneApplicationService.Current.State[GameKey] = gameRaw;

            //Save for application closes and re-opens
            if (IsolatedStorageSettings.ApplicationSettings.Contains(GameKey))
                IsolatedStorageSettings.ApplicationSettings[GameKey] = gameRaw;
            else
                IsolatedStorageSettings.ApplicationSettings.Add(GameKey, gameRaw);
            IsolatedStorageSettings.ApplicationSettings.Save();
        }
        private void ComputerMoveStarted(object sender, EventArguments.PlayerEventArgs e)
        {
            ThinkingStarted = DateTime.Now;
            var thinking = e.Player.PlayerData.Name + " is thinking";
            var thinkinghTimer = new DispatcherTimer();
            thinkinghTimer.Interval = new TimeSpan(0, 0, 0, 0, 600);
            thinkinghTimer.Tick += (obj, arg) => {
                if (ThinkingStarted == default(DateTime) || e.Player.PlayerData.PlayerID != Game.CurrentTurn.Player.PlayerData.PlayerID)
                    ((DispatcherTimer)obj).Stop();
                else if (DateTime.Now.Subtract(ThinkingStarted).TotalSeconds < 2)
                    txtPlayerThinking.Foreground = e.Player.Color;
                else if (txtPlayerThinking.Text == thinking)
                    txtPlayerThinking.Text = thinking + ".";
                else if (txtPlayerThinking.Text == thinking + ".")
                    txtPlayerThinking.Text = thinking + "..";
                else if (txtPlayerThinking.Text == thinking + "..")
                    txtPlayerThinking.Text = thinking + "...";
                else
                    txtPlayerThinking.Text = thinking;
            };
            thinkinghTimer.Start();
        }
        private void ComputerMoveCompleted(object sender, EventArguments.PlayerEventArgs e)
        {
            txtPlayerThinking.Text = "";
            ThinkingStarted = default(DateTime);
        }
        /// <summary>
        /// Game has no more moves event
        /// </summary>
        public void GameOver(object PlayerChanged, EventArguments.GameOverEventArgs e)
        {
            UpdateScore();
            if (e.Winner == Game.Players[0])
            {
                txtYouWin.Visibility = Visibility.Visible;
            }
            else
            {
                txtYouLost.Visibility = Visibility.Visible;
            }
            IsGameInProgress = false;
            ShowNewGameOptions();

            if (Game.Theme == GameModel.ThemeType.Arcade)
            {
                DispatcherTimer playSound = new DispatcherTimer();
                playSound.Interval = new TimeSpan(0,0,0,0,100);
                playSound.Tick += (ot, et) =>
                                      {
                                          /////////////////////////////////////////////////////////////
                                          // http://www.freesound.org/samplesViewSingle.php?id=69316 //
                                          //   69316__meowtek__newbit1.wav Sound effect by Meowtek   //
                                          /////////////////////////////////////////////////////////////
                                          PlaySound("69316__meowtek__newbit1.wav");
                                          ((DispatcherTimer)ot).Stop();
                                      };
                playSound.Start();
            }
        }
 
         /// <summary>
        /// Player changed event
        /// </summary>
        /// <param name="PlayerChanged"></param>
        /// <param name="e"></param>
        public void PlayerChanged(object PlayerChanged, EventArgs e)
        {
            UpdateScore();

            var player = (PlayerView)PlayerChanged;
            if (player == Game.Players[0])
            {
                rclActive1.Opacity = 1d;
                rclActive2.Opacity = 0.2d;

                txtMoves1.Opacity = 1d;
                txtScore1.Opacity = 1d;
                txtTurn1.Opacity = 1d;
                txtName1.Opacity = 1d;

                txtMoves2.Opacity = 0.4d;
                txtScore2.Opacity = 0.4d;
                txtTurn2.Opacity = 0.4d;
                txtName2.Opacity = 0.4d;
            }
            else
            {
                rclActive1.Opacity = 0.2d;
                rclActive2.Opacity = 1d;

                txtMoves1.Opacity = 0.4d;
                txtScore1.Opacity = 0.4d;
                txtTurn1.Opacity = 0.4d;
                txtName1.Opacity = 0.4d;

                txtMoves2.Opacity = 1d;
                txtScore2.Opacity = 1d;
                txtTurn2.Opacity = 1d;
                txtName2.Opacity = 1d;

            }
        }

#endregion
#region Page Events
        protected void btnContinueGame_Click(object sender, RoutedEventArgs e)
        {
            ContinueGame();
        }

        private void btnbtnQuitGame_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.GoBack();
        }
        protected void btnStartGame_Click(object sender, RoutedEventArgs e)
        {
            StartNewGame();
            if (Game.Theme == GameModel.ThemeType.Arcade)
                /////////////////////////////////////////////////////////////
                // http://www.freesound.org/samplesViewSingle.php?id=69316 //
                //   69316__meowtek__newbit1.wav Sound effect by Meowtek   //
                /////////////////////////////////////////////////////////////
                PlaySound("69316__meowtek__newbit1.wav");
        }
        /// <summary>
        /// Navigate to Instructions
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnInstructions_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Instructions.xaml", UriKind.Relative));
        }
        /// <summary>
        /// Navigate to About Box-i
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnAbout_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/About.xaml", UriKind.Relative));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSettings_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
        }
        /// <summary>
        /// Rebuild board when size changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbxSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (IsLoading)
                return;

            BuildNewGame();
        }

        private void lbxPlayer1Type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (IsLoading || lbxPlayer1Type == null)
                return;
#if (DEBUG)
            Game.Players[0].PlayerData.TypeOfPlayer = (PlayerModel.PlayerType)Enum.Parse(typeof(PlayerModel.PlayerType), (lbxPlayer1Type.SelectedItem as ComboBoxItem).Content.ToString(), true);
#else
            BuildNewGame();
#endif
        }
        private void lbxPlayer2Type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (IsLoading || lbxPlayer2Type == null)
                return;
#if (DEBUG)
            Game.Players[1].PlayerData.TypeOfPlayer = (PlayerModel.PlayerType)Enum.Parse(typeof (PlayerModel.PlayerType),(lbxPlayer2Type.SelectedItem as ComboBoxItem).Content.ToString(), true);
#else
            BuildNewGame();
#endif
        }
        private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (Game != null && Game.IsPaused)
            {
                e.Cancel = true;
                ContinueGame();
            }
            else if (!IsOverlayOpen)
            {
                e.Cancel = true;
                ShowPauseOptions();
            }
            else if (lbxSizeX.IsDropDownOpen)
            {
                lbxSizeX.IsDropDownOpen = false;
                e.Cancel = true;
            }
            else if (lbxSizeY.IsDropDownOpen)
            {
                lbxSizeY.IsDropDownOpen = false;
                e.Cancel = true;
            }
            else if (lbxDifficulty.IsDropDownOpen)
            {
                lbxDifficulty.IsDropDownOpen = false;
                e.Cancel = true;
            }
            else if (lbxLayout.IsDropDownOpen)
            {
                lbxLayout.IsDropDownOpen = false;
                e.Cancel = true;
            }
            else if (lbxPlayer1Type.IsDropDownOpen)
            {
                lbxPlayer1Type.IsDropDownOpen = false;
                e.Cancel = true;
            }
            else if (lbxPlayer2Type.IsDropDownOpen)
            {
                lbxPlayer2Type.IsDropDownOpen = false;
                e.Cancel = true;
            }
            
        }
        private void GameSettings_Changed(object sender, EventArgs e)
        {
            Game = null;
        }
        private void btnStartNewGame_Click(object sender, RoutedEventArgs e)
        {
            HidePauseOptions();
            ShowNewGameOptions();
        }
        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            IsLoading = true;
            if (Game == null)
            {
                if (HasSavedGame())
                {
                    IsGameInProgress = true;
#if (DEBUG)
                    BuildSavedGame();
 #else
                        try
                        {
                            BuildSavedGame();
                        }
                        catch(Exception ignoreThisError)
                        {
                            var ignored = ignoreThisError;
                            //Ignore because vesions could break the game recall and the error should be ingnored.
                            BuildNewGame();
                            IsGameInProgress = false;
                        }
#endif
                }
                else
                {
                    BuildNewGame();
                }
            }
            IsLoading = false;
            PersistentSettings.Instance.PropertyChanged += GameSettings_Changed;

        }

        private void btnRunTests_Click(object sender, RoutedEventArgs e)
        {
            IsLoading = true;

            TestDifficultThrow1();
            TestDifficultThrow2();
            TestDifficultThrow3();
            TestDifficultThrow4();
            TestDifficultThrow5();
            TestDifficultThrow6();
            TestDifficultThrow7();
            TestDifficultThrow8();
            TestDifficultTake1();
            TestDifficultTake2();
            TestDifficultTake3();
            TestDifficultTake4();
            TestDifficultTake5();
            TestDifficultTake6();
            TestDifficultGive1();

            btnContinueGameFromNew.Visibility = Visibility.Visible;
            IsLoading = false;
        }
 #endregion
#region methods
        private static Boolean HasSavedGame()
        {

            return PhoneApplicationService.Current.State.ContainsKey(GameKey) || IsolatedStorageSettings.ApplicationSettings.Contains(GameKey);
        }

        /// <summary>
        /// Build game view
        /// </summary>
        private void BuildNewGame()
        {
            if (lbxDifficulty == null)
                return;

            cvsMain.Children.Clear();

            var difficulty = (GameModel.DifficultyType)Enum.Parse(typeof(GameModel.DifficultyType), (lbxDifficulty.SelectedItem as ComboBoxItem).Content.ToString(), true);
            var theme = (GameModel.ThemeType)Enum.Parse(typeof(GameModel.ThemeType), (lbxLayout.SelectedItem as ComboBoxItem).Content.ToString(), true);
            var columns = Byte.Parse((lbxSizeX.SelectedItem as ComboBoxItem).Content.ToString());
            var rows = Byte.Parse((lbxSizeY.SelectedItem as ComboBoxItem).Content.ToString());

            var player1Type = (PlayerModel.PlayerType)Enum.Parse(typeof(PlayerModel.PlayerType), (lbxPlayer1Type.SelectedItem as ComboBoxItem).Content.ToString(), true);
            var player1Name = txtPlayer1Name.Text;
            if (player1Name.Replace(" ", "") == "")
                player1Name = "Me";

            var player2Type = (PlayerModel.PlayerType)Enum.Parse(typeof(PlayerModel.PlayerType), (lbxPlayer2Type.SelectedItem as ComboBoxItem).Content.ToString(), true);
            var player2Name = txtPlayer2Name.Text;
            if (player2Name.Replace(" ", "") == "")
                player2Name = DeviceExtendedProperties.GetValue("DeviceName").ToString();

            var players = new PlayerView[2];


            players[0] = new PlayerView(1, player1Name, AccentColor(theme).Color, player1Type);
            players[1] = new PlayerView(2, player2Name, SecondaryAccentColor(theme).Color, player2Type);

            Game = new GameView(cvsMain,
                (GameModel.ThemeType)Enum.Parse(typeof(GameModel.ThemeType), (lbxLayout.SelectedItem as ComboBoxItem).Content.ToString(), true),
                IsBackgroundDark,
                difficulty, columns, rows, players);

            Game.OnComputerMoveStarted += ComputerMoveStarted;
            Game.OnComputerMoveCompleted += ComputerMoveCompleted;
            Game.OnAfterMoveMade += MoveMade;
            Game.OnAfterActivationComplete += MoveActivationComplete;
            Game.OnPlayerChanged += PlayerChanged;
            Game.OnGameOver += GameOver;

            IsGameInProgress = false;
            BuildGameUI();
        }
        
        /// <summary>
        /// Build game view
        /// </summary>
        private void BuildSavedGame()
        {
            if (lbxDifficulty == null)
                return;

            var gameRaw = (PhoneApplicationService.Current.State.ContainsKey(GameKey))
                              ? PhoneApplicationService.Current.State[GameKey].ToString()
                              : IsolatedStorageSettings.ApplicationSettings[GameKey].ToString();

            BuildSavedGame(gameRaw);
        }

        /// <summary>
        /// Build game view
        /// </summary>
        private void BuildSavedGame(String gameRaw)
        {
            cvsMain.Children.Clear();
            Game = GameView.Load(gameRaw, cvsMain, IsBackgroundDark);
            Game.OnComputerMoveStarted += ComputerMoveStarted;
            Game.OnComputerMoveCompleted += ComputerMoveCompleted;
            Game.OnAfterMoveMade += MoveMade;
            Game.OnAfterActivationComplete += MoveActivationComplete;
            Game.OnPlayerChanged += PlayerChanged;
            Game.OnGameOver += GameOver;

            //Board UI
            foreach (ComboBoxItem item in lbxDifficulty.Items)
                if (item.Content.Equals(Game.Difficulty.ToString()))
                    lbxDifficulty.SelectedItem = item;

            foreach (ComboBoxItem item in lbxSizeX.Items)
                if (item.Content.Equals(Game.GameData.Columns.ToString()))
                    lbxSizeX.SelectedItem = item;

            foreach (ComboBoxItem item in lbxSizeY.Items)
                if (item.Content.Equals(Game.GameData.Rows.ToString()))
                    lbxSizeY.SelectedItem = item;

            foreach (ComboBoxItem item in lbxLayout.Items)
                if (item.Content.Equals(Game.Theme.ToString()))
                    lbxLayout.SelectedItem = item;

            //Player UI
            txtPlayer1Name.Text = Game.Players[0].PlayerData.Name;
            txtPlayer2Name.Text = Game.Players[1].PlayerData.Name;

            foreach (ComboBoxItem item in lbxPlayer1Type.Items)
                if (item.Content.Equals(Game.Players[0].PlayerData.TypeOfPlayer.ToString()))
                    lbxPlayer1Type.SelectedItem = item;

            foreach (ComboBoxItem item in lbxPlayer2Type.Items)
                if (item.Content.Equals(Game.Players[1].PlayerData.TypeOfPlayer.ToString()))
                    lbxPlayer2Type.SelectedItem = item;

            BuildGameUI();
            UpdateScore();
        }

        /// <summary>
        /// Build game board
        /// </summary>
        private void BuildGameUI()
        {
            if (lbxDifficulty == null)
                return;
    
            txtName1.Text = Game.Players[0].PlayerData.Name;
            txtName2.Text = Game.Players[1].PlayerData.Name;

            // Scale the rectangle.
            if (Game.GameData.Columns <= 3 && Game.GameData.Rows <= 4)
            {
                scale.ScaleX = 2.7;
                scale.ScaleY = 2.7;
            }
            else if (Game.GameData.Columns <= 4 && Game.GameData.Rows <= 5)
            {
                scale.ScaleX = 2.1;
                scale.ScaleY = 2.1;
            }
            else if (Game.GameData.Columns <= 5 && Game.GameData.Rows <= 6)
            {
                scale.ScaleX = 1.7;
                scale.ScaleY = 1.7;
            }
            else if (Game.GameData.Columns <= 5 && Game.GameData.Rows <= 7)
            {
                scale.ScaleX = 1.55;
                scale.ScaleY = 1.55;
            }
            else if (Game.GameData.Columns <= 6 && Game.GameData.Rows <= 7)
            {
                scale.ScaleX = 1.4;
                scale.ScaleY = 1.4;
            }
            else if (Game.GameData.Columns <= 6 && Game.GameData.Rows <= 8)
            {
                scale.ScaleX = 1.35;
                scale.ScaleY = 1.35;
            }
            else if (Game.GameData.Columns <= 7 && Game.GameData.Rows <= 9)
            {
                scale.ScaleX = 1.2;
                scale.ScaleY = 1.2;
            }
            else if (Game.GameData.Columns <= 8 && Game.GameData.Rows <= 9)
            {
                scale.ScaleX = 1.1;
                scale.ScaleY = 1.1;
            }
            else if (Game.GameData.Columns <= 8 && Game.GameData.Rows <= 10)
            {
                scale.ScaleX = 1.05;
                scale.ScaleY = 1.05;
            }
            else if (Game.GameData.Columns <= 8 && Game.GameData.Rows <= 10)
            {
                scale.ScaleX = 0.95;
                scale.ScaleY = 0.95;
            }
            else
            {
                scale.ScaleX = 0.925;
                scale.ScaleY = 0.925;
            }

            btnContinueGameFromNew.Visibility = (IsGameInProgress && Game.MoveHistory.Contains(0))
                                                    ? Visibility.Visible
                                                    : Visibility.Collapsed;

            imgParchment.Visibility = (Game.Theme == GameModel.ThemeType.Traditional) ? Visibility.Visible : Visibility.Collapsed;
            IsOverlayOpen = true;

            txtYouWin.Visibility = Visibility.Collapsed;
            txtYouLost.Visibility = Visibility.Collapsed;



            lbxSizeX.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;
            lbxSizeY.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;
            lbxDifficulty.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;
            lbxLayout.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;
            lbxPlayer1Type.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;
            lbxPlayer2Type.Foreground = (Game.Theme == GameModel.ThemeType.Arcade) ? new SolidColorBrush(Colors.Black) : ForegroundColor;


            //btnAbout.Background = AccentColor(Game.Theme);
            //btnInstructions.Background = AccentColor(Game.Theme);
            //btnContinueGame.Background = AccentColor(Game.Theme);
            //btnStartGame.Background = AccentColor(Game.Theme);
            //btnStartNewGame.Background = AccentColor(Game.Theme);
            //btnContinueGameFromNew.Background = AccentColor(Game.Theme);
            //btnSettings.Background = AccentColor(Game.Theme);

            Foreground = ForegroundColor;
            ApplicationTitle.Foreground = ForegroundColor;
            PageTitle.Foreground = ForegroundColor;

            rclActive1.Fill = Game.Players[0].Color;
            rclActive2.Fill = Game.Players[1].Color;


#if (DEBUG)
            lbxPlayer1Type.IsEnabled = true;
            btnRunTests.Visibility = Visibility.Visible;
            //btnRunTests.Background = AccentColor(Game.Theme);
#else
            lbxPlayer1Type.IsEnabled = false;
            foreach (ComboBoxItem item in lbxPlayer1Type.Items)
                if (item.Content.Equals("Human"))
                    lbxPlayer1Type.SelectedItem = item;
#endif

            UpdateScore();
        }
        private void ShowNewGameOptions()
        {
            IsOverlayOpen = true;
            spNewGame.Visibility = Visibility.Visible;

            btnContinueGameFromNew.Visibility = (IsGameInProgress && Game.MoveHistory.Contains(0))
                                                    ? Visibility.Visible
                                                    : Visibility.Collapsed;
        }
        private void HideNewGameOptions()
        {
            IsOverlayOpen = false;
            spNewGame.Visibility = Visibility.Collapsed;
        }
        private void ShowPauseOptions()
        {
            Game.IsPaused = true;
            IsOverlayOpen = true;
            spPause.Visibility = Visibility.Visible;
            var rawData = Game.ToString();
        }
        private void HidePauseOptions()
        {
            IsOverlayOpen = false;
            spPause.Visibility = Visibility.Collapsed;
        }
        private void UpdateScore()
        {
            txtMoves1.Text = Game.Players[0].PlayerData.Moves.ToString();
            txtMoves2.Text = Game.Players[1].PlayerData.Moves.ToString();
            txtScore1.Text = Game.Players[0].PlayerData.Points.ToString();
            txtScore2.Text = Game.Players[1].PlayerData.Points.ToString();
            txtTurn1.Text = Game.Players[0].PlayerData.Turns.ToString();
            txtTurn2.Text = Game.Players[1].PlayerData.Turns.ToString();
            
        }
        private void StartNewGame()
        {
            HideNewGameOptions();
            BuildNewGame();
            Game.Start();
            IsGameInProgress = true;
            IsOverlayOpen = false;
        }
        private void ContinueGame()
        {
            HidePauseOptions();
            HideNewGameOptions();
            
            IsGameInProgress = true;
            Game.IsPaused = false;
            Game.NextMove();
        }
        protected SolidColorBrush AccentColor(GameModel.ThemeType theme)
        {
            return
                new SolidColorBrush((theme == GameModel.ThemeType.Traditional)
                                        ? Colors.Brown
                                        : PersistentSettings.Instance.AccentColor);
        }
        protected SolidColorBrush SecondaryAccentColor(GameModel.ThemeType theme)
        {
            return
                new SolidColorBrush((theme == GameModel.ThemeType.Traditional)
                                        ? Colors.Brown
                                        : PersistentSettings.Instance.SecondaryAccentColor);
        }
        private void Vibrate(Int32 milliseconds)
        {
            if (PersistentSettings.Instance.IsVibrationEnabled)
                VibrateController.Default.Start(TimeSpan.FromMilliseconds(milliseconds));
        }

        private void PlaySound(String soundFile)
        {
            if (!PersistentSettings.Instance.IsSoundEnabled)
                return;
                try
                {
                    StreamResourceInfo streamInfo =
                        Application.GetResourceStream(new Uri("/Boxi;component/Sounds/" + soundFile, UriKind.Relative));
                    SoundEffect se = SoundEffect.FromStream(streamInfo.Stream);
                    SoundEffectInstance soundInstance = se.CreateInstance();
                    soundInstance.Play();
                }
                catch (Exception ex)
                {
                    //Not critical
                }
        }
#endregion
#region Tests
        private void TestDifficultThrow1()
        {
            BuildSavedGame("3,4\n1|Me|255~27~161~226|Computer,2|XDeviceEmulator|255~228~94~29|Human\n5,26,12,22,19,13,20,30,6,24,3,8,14,28,4,1,25,29,11,15,18,7,10,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1},Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 21)
                throw new Exception("Test error TestDifficultThrow1");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow2()
        {
            BuildSavedGame("3,4\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n13,19,20,25,30,1,6,7,14,12,21,22,28,27,5,11,4,8,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 18)
                throw new Exception("Test error TestDifficultThrow2");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow3()
        {
            BuildSavedGame( "4,5\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n21,2,26,22,35,16,44,46,49,6,38,5,39,8,37,19,47,32,24,13,20,3,9,4,14,41,42,43,48,36,33,28,23,27,31,40,45,30,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 29)
                throw new Exception("Test error TestDifficultThrow3");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow4()
        {
            BuildSavedGame("4,5\n1|Mike|255~165~42~42|Human,2|HD7|255~165~42~42|Computer\n21,30,16,19,11,33,10,9,1,29,2,3,4,23,18,37,22,40,31,48,39,41,49,47,5,6,7,46,42,14,15,20,8,12,17,13,27,26,25,24,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1}, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 32)
                throw new Exception("Test error TestDifficultThrow4");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow5()
        {
            BuildSavedGame("5,7\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n31,68,20,5,21,66,81,78,80,58,79,67,69,48,70,47,71,43,59,30,55,45,49,18,46,62,50,10,22,33,32,12,9,29,41,3,19,1,28,2,39,77,11,16,27,38,44,6,7,54,53,52,60,65,64,63,57,51,61,56,76,75,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nArcade");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 82)
                throw new Exception("Test error TestDifficultThrow5");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow6()
        {
            BuildSavedGame("6,8\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n24,71,37,67,50,58,63,27,76,103,89,41,102,68,101,11,88,47,75,36,62,85,49,92,23,19,10,105,9,14,22,57,35,104,87,1,100,52,106,2,33,83,46,66,59,12,72,78,91,31,39,26,6,13,80,21,20,110,97,3,16,29,42,5,18,25,32,38,44,45,51,7,8,28,15,34,40,53,60,48,55,61,54,65,64,70,77,84,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nArcade");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 109)
                throw new Exception("Test error TestDifficultThrow6");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultThrow7()
        {
            BuildSavedGame("5,7\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n31,40,47,21,48,2,43,34,55,38,60,71,59,4,58,41,57,67,56,25,50,12,33,10,22,11,6,75,28,24,13,74,14,81,79,63,78,26,77,3,82,76,70,17,72,73,68,62,61,39,45,51,44,49,54,53,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nArcade");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1}, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 35)
                throw new Exception("Test error TestDifficultThrow7");
            Game.Moves[moveID - 1].Assign();
        }
         private void TestDifficultThrow8()
        {
            BuildSavedGame("5,7\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n20,30,31,50,42,63,41,77,53,64,75,39,32,43,15,9,16,40,22,68,33,56,44,5,55,79,60,65,76,13,18,2,29,72,28,3,17,61,6,52,1,78,80,4,66,10,11,71,82,59,70,81,38,27,21,26,37,48,49,54,19,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nArcade");
             var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1}, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
             if (moveID != 46)
                throw new Exception("Test error TestDifficultThrow8");
             Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake1()
        {
            BuildSavedGame("3,4\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n6,3,13,27,20,16,31,26,17,4,11,2,18,1,15,25,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1}, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 10)
                throw new Exception("Test error TestDifficultTake1");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake2()
        {
            BuildSavedGame("3,4\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n13,23,9,27,8,19,11,21,14,6,7,25,1,28,29,18,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1},Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID; 
            if (moveID !=  5)
                throw new Exception("Test error TestDifficultThrow2");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake3()
        {
            BuildSavedGame("5,7\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n20,3,31,17,36,4,35,47,53,80,69,27,64,45,46,55,50,38,61,77,67,18,68,11,57,16,79,19,78,71,81,1,66,48,49,15,70,2,6,34,8,28,44,43,33,32,23,12,7,13,24,29,30,25,14,9,5,60,54,59,10,65,72,73,74,75,76,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] {0, 1},Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 51)  
                throw new Exception("Test error TestDifficultTake3");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake4()
        {
            BuildSavedGame("4,5\n1|Me|255~165~42~42|Human,2|HD7|255~165~42~42|Human\n8,10,17,29,26,18,30,16,24,42,15,5,2,38,3,39,23,36,32,45,41,4,48,31,49,1,9,6,13,22,27,37,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 46)
                throw new Exception("Test error TestDifficultTake4");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake5()
        {
            BuildSavedGame("4,6\n1|Me|255~165~42~42|Human,2|HD7|255~165~42~42|Human\n8,53,17,7,26,5,35,27,44,41,9,19,18,32,36,24,45,51,54,38,34,37,20,55,16,52,2,14,1,43,56,47,42,46,50,3,12,21,57,48,39,30,25,29,33,23,28,6,15,10,11,4,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 13)
                throw new Exception("Test error TestDifficultTake5");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultTake6()
        {
            BuildSavedGame("5,7\n1|Me|255~229~20~0|Human,2|HD7|255~26~235~255|Human\n20,30,31,50,42,63,41,77,53,64,75,39,32,43,15,9,16,40,22,68,33,56,44,5,55,79,60,65,76,13,18,2,29,72,28,3,17,61,6,52,1,78,80,4,66,10,11,71,82,59,70,81,38,27,21,26,37,48,49,54,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nArcade");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 24)
                throw new Exception("Test error TestDifficultTake6");
            Game.Moves[moveID - 1].Assign();
        }
        private void TestDifficultGive1()
        {
            BuildSavedGame("4,6\n1|Me|255~165~42~42|Human,2|HD7|255~165~42~42|Human\n8,53,17,7,26,5,35,27,44,41,9,19,18,32,36,24,45,51,54,38,34,37,20,55,16,52,2,14,1,43,56,47,42,46,50,3,12,21,57,48,39,30,25,29,33,23,28,0,0,0,0,0,0,0,0,0,0,0\nDifficult\nTraditional");
            var moveID = GameModel.GetComputerMove(Game.MoveOptions, Game.MoveHistory, new SByte[] { 0, 1 }, Game.CurrentTurn.Player.PlayerData.PlayerID, Game.Difficulty, Game.GameData).MoveID;
            if (moveID != 6 && moveID != 10 && moveID != 11 && moveID != 15)
                throw new Exception("Test error TestDifficultGive1");
            Game.Moves[moveID - 1].Assign();
        }
#endregion


    }
}